/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package SessionBeans.web;

import SessionBeans.Sharing.RightsService;
import SessionBeans.Sharing.SharingService;
import SessionBeans.web.beans.FolderInfo;
import SessionBeans.web.beans.FileInfo;
import SessionBeans.entites.FileService;
import SessionBeans.entites.FolderService;
import SessionBeans.logs.FileChangeLogService;
import SessionBeans.logs.FolderChangeLogService;
import SessionBeans.web.beans.FolderTypeEnum;
import SessionBeans.web.beans.OwnerUser;
import api.Rights.RightsEnum;
import entities.*;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author Tomas
 */
@Stateless
@LocalBean
public class FilesTableSessionBean {

    @EJB
    private RightsService rightsService;
    @EJB
    private SharingService sharingService;
    @EJB
    private FileService fileService;
    @EJB
    private FolderService folderService;
    @EJB
    private FolderChangeLogService folderChangeLogService;
    @EJB
    private FileChangeLogService fileChangeLogService;
    @PersistenceContext(unitName = "tCloudEE-ejbPU")
    private EntityManager em;

    public FolderInfo loadUserFiles(Long userId) {
        User find = em.find(User.class, userId);
        Folder rootFolder = find.getAccountHeaderList().get(0).getRootFolder();

        rootFolder.getFilesList().size();
        rootFolder.getFolderList().size();
        FolderInfo buildInfo = buildInfo(rootFolder, find);

        buildInfo.getFolders().add(sharingService.loadShareData(userId));

        return buildInfo;
    }

    public FolderInfo loadFiles(Long folderId, Long userId) {
        if (folderId == -1) {
            return sharingService.loadShareData(userId);
        } else {
            Folder rootFolder = em.find(Folder.class, folderId);
            User caller = em.find(User.class, userId);
            rootFolder.getFilesList().size();
            rootFolder.getFolderList().size();

            FolderInfo buildInfo = buildInfo(rootFolder, caller);

            if (caller.getAccountHeaderList().get(0).getRootFolder().getId() == folderId) {
                buildInfo.getFolders().add(sharingService.loadShareData(userId));
            }

            return buildInfo;
        }
    }

    private OwnerUser loadOwner(Folder folder) {
        Folder pom = folder;
        while (pom.getParentFolder() != null) {
            pom = pom.getParentFolder();
        }
        AccountHeader singleResult = em.createQuery("Select OBJECT(u) from AccountHeader u where u.rootFolder.id = " + pom.getId(), AccountHeader.class).getSingleResult();

        return new OwnerUser(singleResult.getOwnerUser().getId(), singleResult.getOwnerUser().getName());
    }

    private Rights loadRights(Folder folder, User caller) {
        if (loadOwner(folder).getUserName().equalsIgnoreCase(caller.getName())) {
            return rightsService.loadRights(RightsEnum.DELETE);
        }

        List<SharedFolder> loadSharedFolder = sharingService.loadSharedFolder(folder.getId());
        Rights rights = null;

        for (SharedFolder sharedFolder : loadSharedFolder) {
            if (sharedFolder.getSharedUser().getName().equalsIgnoreCase(caller.getName())) {
                return sharedFolder.getRights();
            }
        }
        if (folder.getParentFolder() != null) {
            rights = loadRights(folder.getParentFolder(), caller);
        }
        return rights;
    }

    private Rights loadRights(File file, User caller) {
        return loadRights(file.getFolderId(), caller);
    }

    public FileBlob loadFileValue(Long fileBlobId) {
        return em.find(FileBlob.class, fileBlobId);
    }

    private FolderInfo buildInfo(Folder folder, User caller) {
        FolderTypeEnum type = FolderTypeEnum.MY;
        OwnerUser owner = loadOwner(folder);
        if (owner.getUserId() != caller.getId()) {
            type = FolderTypeEnum.SHARED;
        }
        FolderInfo root = new FolderInfo(folder, loadFolderLastChange(folder), type, owner, loadRights(folder, caller));
        root.setOwner(loadOwner(folder));
        List<FolderInfo> childsFolder = new ArrayList<>();
        List<FileInfo> childsFile = new ArrayList<>();

        for (Folder childFolder : folder.getFolderList()) {
            childsFolder.add(buildChildFolderInfo(childFolder, caller));
        }

        for (File file : folder.getFilesList()) {
            childsFile.add(buildFileInfo(file, caller));
        }

//        childsFolder.add(sharingService.loadShareData(user.getUserId()));

        root.setFiles(childsFile);
        root.setFolders(childsFolder);
        return root;
    }

    private FolderInfo buildChildFolderInfo(Folder folder, User caller) {
        return new FolderInfo(folder, loadFolderLastChange(folder), FolderTypeEnum.MY, loadOwner(folder), loadRights(folder, caller));
    }

    private FileInfo buildFileInfo(File file, User caller) {
        return new FileInfo(file, loadRights(file, caller), loadOwner(file.getFolderId()), fileService.loadFileSize(file), loadFileLastChange(file));
    }

    private FolderChangeLog loadFolderLastChange(Folder folder) {
        return folderChangeLogService.loadLastChange(folder);
    }

    private FileChangeLog loadFileLastChange(File file) {
        return fileChangeLogService.loadLastChange(file);
    }

    public FolderInfo createFolder(Long userId, Long parentFolderId, String folderName) {
        folderService.newFolder(userId, folderName, parentFolderId);
        updateAccHeader(userId);
        updateAccHeaderFolder(parentFolderId);
        return loadFiles(parentFolderId, userId);
    }

    public FolderInfo uploadFile(Long userId, Long folderId, String name, byte[] value) {
        File newFile = fileService.newFile(userId, name, value, folderId);
        updateAccHeader(userId);
        updateAccHeaderFile(newFile.getId());
        return loadFiles(folderId, userId);
    }

    private void updateAccHeader(Long userId) {
        User find = em.find(User.class, userId);
        AccountHeader acc = find.getAccountHeaderList().get(0);

        acc.setVersion(acc.getVersion() + 1);

        em.persist(acc);
    }

    private void updateAccHeaderFolder(Long folderId) {
        List<SharedFolder> loadSharedFolder = sharingService.loadSharedFolder(folderId);
        Folder find = em.find(Folder.class, folderId);

        for (SharedFolder sharedFolder : loadSharedFolder) {
            updateAccHeader(sharedFolder.getOwnerUser().getId());
        }

        while (find.getParentFolder() != null) {
            find = find.getParentFolder();
            updateAccHeaderFolder(find.getId());
        }

    }

    private void updateAccHeaderFile(Long fileId) {
        List<SharedFile> loadSharedFile = sharingService.loadSharedFile(fileId);
        File find = em.find(File.class, fileId);
        boolean findS = false;
        for (SharedFile sharedFile : loadSharedFile) {
            findS = true;
            updateAccHeader(sharedFile.getOwnerUser().getId());
        }
        if(!findS){
            updateAccHeaderFolder(find.getFolderId().getId());
        }
    }
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
}
